1
2 package org.apache.solr.parser;
3
4 import java.io.StringReader;
5 import java.util.ArrayList;
6 import java.util.List;
7 import java.util.Locale;
8
9 import org.apache.lucene.analysis.Analyzer;
10 import org.apache.lucene.document.DateTools;
11 import org.apache.lucene.search.BooleanClause;
12 import org.apache.lucene.search.Query;
13 import org.apache.lucene.search.TermRangeQuery;
14 import org.apache.lucene.search.TermQuery;
15 import org.apache.lucene.util.Version;
16 import org.apache.solr.search.SyntaxError;
17 import org.apache.solr.search.QParser;
18
19
20 public class QueryParser extends SolrQueryParserBase implements QueryParserConstants {
21
22
23 static public enum Operator { OR, AND }
24
25 public QueryParser(Version matchVersion, String defaultField, QParser parser) {
26 this(new FastCharStream(new StringReader("")));
27 init(matchVersion, defaultField, parser);
28 }
29
30
31
32 final public int Conjunction() throws ParseException {
33 int ret = CONJ_NONE;
34 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
35 case AND:
36 case OR:
37 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
38 case AND:
39 jj_consume_token(AND);
40 ret = CONJ_AND;
41 break;
42 case OR:
43 jj_consume_token(OR);
44 ret = CONJ_OR;
45 break;
46 default:
47 jj_la1[0] = jj_gen;
48 jj_consume_token(-1);
49 throw new ParseException();
50 }
51 break;
52 default:
53 jj_la1[1] = jj_gen;
54 ;
55 }
56 {if (true) return ret;}
57 throw new Error("Missing return statement in function");
58 }
59
60 final public int Modifiers() throws ParseException {
61 int ret = MOD_NONE;
62 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
63 case NOT:
64 case PLUS:
65 case MINUS:
66 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
67 case PLUS:
68 jj_consume_token(PLUS);
69 ret = MOD_REQ;
70 break;
71 case MINUS:
72 jj_consume_token(MINUS);
73 ret = MOD_NOT;
74 break;
75 case NOT:
76 jj_consume_token(NOT);
77 ret = MOD_NOT;
78 break;
79 default:
80 jj_la1[2] = jj_gen;
81 jj_consume_token(-1);
82 throw new ParseException();
83 }
84 break;
85 default:
86 jj_la1[3] = jj_gen;
87 ;
88 }
89 {if (true) return ret;}
90 throw new Error("Missing return statement in function");
91 }
92
93
94 final public Query TopLevelQuery(String field) throws ParseException, SyntaxError {
95 Query q;
96 q = Query(field);
97 jj_consume_token(0);
98 {if (true) return q;}
99 throw new Error("Missing return statement in function");
100 }
101
102 final public Query Query(String field) throws ParseException, SyntaxError {
103 List<BooleanClause> clauses = new ArrayList<BooleanClause>();
104 Query q, firstQuery=null;
105 int conj, mods;
106 mods = Modifiers();
107 q = Clause(field);
108 addClause(clauses, CONJ_NONE, mods, q);
109 if (mods == MOD_NONE)
110 firstQuery=q;
111 label_1:
112 while (true) {
113 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
114 case AND:
115 case OR:
116 case NOT:
117 case PLUS:
118 case MINUS:
119 case BAREOPER:
120 case LPAREN:
121 case STAR:
122 case QUOTED:
123 case TERM:
124 case PREFIXTERM:
125 case WILDTERM:
126 case REGEXPTERM:
127 case RANGEIN_START:
128 case RANGEEX_START:
129 case LPARAMS:
130 case FILTER:
131 case NUMBER:
132 ;
133 break;
134 default:
135 jj_la1[4] = jj_gen;
136 break label_1;
137 }
138 conj = Conjunction();
139 mods = Modifiers();
140 q = Clause(field);
141 addClause(clauses, conj, mods, q);
142 }
143 if (clauses.size() == 1 && firstQuery != null)
144 {if (true) return firstQuery;}
145 else {
146 {if (true) return getBooleanQuery(clauses);}
147 }
148 throw new Error("Missing return statement in function");
149 }
150
151 final public Query Clause(String field) throws ParseException, SyntaxError {
152 Query q;
153 Token fieldToken=null, boost=null;
154 Token localParams=null;
155 if (jj_2_1(2)) {
156 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
157 case TERM:
158 fieldToken = jj_consume_token(TERM);
159 jj_consume_token(COLON);
160 field=discardEscapeChar(fieldToken.image);
161 break;
162 case STAR:
163 jj_consume_token(STAR);
164 jj_consume_token(COLON);
165 field="*";
166 break;
167 default:
168 jj_la1[5] = jj_gen;
169 jj_consume_token(-1);
170 throw new ParseException();
171 }
172 } else {
173 ;
174 }
175 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
176 case BAREOPER:
177 case STAR:
178 case QUOTED:
179 case TERM:
180 case PREFIXTERM:
181 case WILDTERM:
182 case REGEXPTERM:
183 case RANGEIN_START:
184 case RANGEEX_START:
185 case NUMBER:
186 q = Term(field);
187 break;
188 case LPAREN:
189 jj_consume_token(LPAREN);
190 q = Query(field);
191 jj_consume_token(RPAREN);
192 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
193 case CARAT:
194 jj_consume_token(CARAT);
195 boost = jj_consume_token(NUMBER);
196 break;
197 default:
198 jj_la1[6] = jj_gen;
199 ;
200 }
201 break;
202 case FILTER:
203 jj_consume_token(FILTER);
204 q = Query(field);
205 jj_consume_token(RPAREN);
206 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
207 case CARAT:
208 jj_consume_token(CARAT);
209 boost = jj_consume_token(NUMBER);
210 break;
211 default:
212 jj_la1[7] = jj_gen;
213 ;
214 }
215 q=getFilter(q);
216 break;
217 case LPARAMS:
218 localParams = jj_consume_token(LPARAMS);
219 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
220 case CARAT:
221 jj_consume_token(CARAT);
222 boost = jj_consume_token(NUMBER);
223 break;
224 default:
225 jj_la1[8] = jj_gen;
226 ;
227 }
228 q=getLocalParams(field, localParams.image);
229 break;
230 default:
231 jj_la1[9] = jj_gen;
232 jj_consume_token(-1);
233 throw new ParseException();
234 }
235 {if (true) return handleBoost(q, boost);}
236 throw new Error("Missing return statement in function");
237 }
238
239 final public Query Term(String field) throws ParseException, SyntaxError {
240 Token term, boost=null, fuzzySlop=null, goop1, goop2;
241 boolean prefix = false;
242 boolean wildcard = false;
243 boolean fuzzy = false;
244 boolean regexp = false;
245 boolean startInc=false;
246 boolean endInc=false;
247 Query q;
248 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
249 case BAREOPER:
250 case STAR:
251 case TERM:
252 case PREFIXTERM:
253 case WILDTERM:
254 case REGEXPTERM:
255 case NUMBER:
256 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
257 case TERM:
258 term = jj_consume_token(TERM);
259 break;
260 case STAR:
261 term = jj_consume_token(STAR);
262 wildcard=true;
263 break;
264 case PREFIXTERM:
265 term = jj_consume_token(PREFIXTERM);
266 prefix=true;
267 break;
268 case WILDTERM:
269 term = jj_consume_token(WILDTERM);
270 wildcard=true;
271 break;
272 case REGEXPTERM:
273 term = jj_consume_token(REGEXPTERM);
274 regexp=true;
275 break;
276 case NUMBER:
277 term = jj_consume_token(NUMBER);
278 break;
279 case BAREOPER:
280 term = jj_consume_token(BAREOPER);
281 term.image = term.image.substring(0,1);
282 break;
283 default:
284 jj_la1[10] = jj_gen;
285 jj_consume_token(-1);
286 throw new ParseException();
287 }
288 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
289 case FUZZY_SLOP:
290 fuzzySlop = jj_consume_token(FUZZY_SLOP);
291 fuzzy=true;
292 break;
293 default:
294 jj_la1[11] = jj_gen;
295 ;
296 }
297 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
298 case CARAT:
299 jj_consume_token(CARAT);
300 boost = jj_consume_token(NUMBER);
301 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
302 case FUZZY_SLOP:
303 fuzzySlop = jj_consume_token(FUZZY_SLOP);
304 fuzzy=true;
305 break;
306 default:
307 jj_la1[12] = jj_gen;
308 ;
309 }
310 break;
311 default:
312 jj_la1[13] = jj_gen;
313 ;
314 }
315 q = handleBareTokenQuery(getField(field), term, fuzzySlop, prefix, wildcard, fuzzy, regexp);
316 break;
317 case RANGEIN_START:
318 case RANGEEX_START:
319 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
320 case RANGEIN_START:
321 jj_consume_token(RANGEIN_START);
322 startInc=true;
323 break;
324 case RANGEEX_START:
325 jj_consume_token(RANGEEX_START);
326 break;
327 default:
328 jj_la1[14] = jj_gen;
329 jj_consume_token(-1);
330 throw new ParseException();
331 }
332 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
333 case RANGE_GOOP:
334 goop1 = jj_consume_token(RANGE_GOOP);
335 break;
336 case RANGE_QUOTED:
337 goop1 = jj_consume_token(RANGE_QUOTED);
338 break;
339 default:
340 jj_la1[15] = jj_gen;
341 jj_consume_token(-1);
342 throw new ParseException();
343 }
344 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
345 case RANGE_TO:
346 jj_consume_token(RANGE_TO);
347 break;
348 default:
349 jj_la1[16] = jj_gen;
350 ;
351 }
352 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
353 case RANGE_GOOP:
354 goop2 = jj_consume_token(RANGE_GOOP);
355 break;
356 case RANGE_QUOTED:
357 goop2 = jj_consume_token(RANGE_QUOTED);
358 break;
359 default:
360 jj_la1[17] = jj_gen;
361 jj_consume_token(-1);
362 throw new ParseException();
363 }
364 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
365 case RANGEIN_END:
366 jj_consume_token(RANGEIN_END);
367 endInc=true;
368 break;
369 case RANGEEX_END:
370 jj_consume_token(RANGEEX_END);
371 break;
372 default:
373 jj_la1[18] = jj_gen;
374 jj_consume_token(-1);
375 throw new ParseException();
376 }
377 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
378 case CARAT:
379 jj_consume_token(CARAT);
380 boost = jj_consume_token(NUMBER);
381 break;
382 default:
383 jj_la1[19] = jj_gen;
384 ;
385 }
386 boolean startOpen=false;
387 boolean endOpen=false;
388 if (goop1.kind == RANGE_QUOTED) {
389 goop1.image = goop1.image.substring(1, goop1.image.length()-1);
390 } else if ("*".equals(goop1.image)) {
391 startOpen=true;
392 }
393 if (goop2.kind == RANGE_QUOTED) {
394 goop2.image = goop2.image.substring(1, goop2.image.length()-1);
395 } else if ("*".equals(goop2.image)) {
396 endOpen=true;
397 }
398 q = getRangeQuery(getField(field), startOpen ? null : discardEscapeChar(goop1.image), endOpen ? null : discardEscapeChar(goop2.image), startInc, endInc);
399 break;
400 case QUOTED:
401 term = jj_consume_token(QUOTED);
402 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
403 case FUZZY_SLOP:
404 fuzzySlop = jj_consume_token(FUZZY_SLOP);
405 break;
406 default:
407 jj_la1[20] = jj_gen;
408 ;
409 }
410 switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
411 case CARAT:
412 jj_consume_token(CARAT);
413 boost = jj_consume_token(NUMBER);
414 break;
415 default:
416 jj_la1[21] = jj_gen;
417 ;
418 }
419 q = handleQuotedTerm(getField(field), term, fuzzySlop);
420 break;
421 default:
422 jj_la1[22] = jj_gen;
423 jj_consume_token(-1);
424 throw new ParseException();
425 }
426 {if (true) return handleBoost(q, boost);}
427 throw new Error("Missing return statement in function");
428 }
429
430 private boolean jj_2_1(int xla) {
431 jj_la = xla; jj_lastpos = jj_scanpos = token;
432 try { return !jj_3_1(); }
433 catch(LookaheadSuccess ls) { return true; }
434 finally { jj_save(0, xla); }
435 }
436
437 private boolean jj_3R_3() {
438 if (jj_scan_token(STAR)) return true;
439 if (jj_scan_token(COLON)) return true;
440 return false;
441 }
442
443 private boolean jj_3R_2() {
444 if (jj_scan_token(TERM)) return true;
445 if (jj_scan_token(COLON)) return true;
446 return false;
447 }
448
449 private boolean jj_3_1() {
450 Token xsp;
451 xsp = jj_scanpos;
452 if (jj_3R_2()) {
453 jj_scanpos = xsp;
454 if (jj_3R_3()) return true;
455 }
456 return false;
457 }
458
459
460 public QueryParserTokenManager token_source;
461
462 public Token token;
463
464 public Token jj_nt;
465 private int jj_ntk;
466 private Token jj_scanpos, jj_lastpos;
467 private int jj_la;
468 private int jj_gen;
469 final private int[] jj_la1 = new int[23];
470 static private int[] jj_la1_0;
471 static private int[] jj_la1_1;
472 static {
473 jj_la1_init_0();
474 jj_la1_init_1();
475 }
476 private static void jj_la1_init_0() {
477 jj_la1_0 = new int[] {0x6000,0x6000,0x38000,0x38000,0xfb4fe000,0x2400000,0x800000,0x800000,0x800000,0xfb4c0000,0x3a440000,0x4000000,0x4000000,0x800000,0xc0000000,0x0,0x0,0x0,0x0,0x800000,0x4000000,0x800000,0xfb440000,};
478 }
479 private static void jj_la1_init_1() {
480 jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x7,0x4,0x0,0x0,0x0,0x0,0xc0,0x8,0xc0,0x30,0x0,0x0,0x0,0x4,};
481 }
482 final private JJCalls[] jj_2_rtns = new JJCalls[1];
483 private boolean jj_rescan = false;
484 private int jj_gc = 0;
485
486
487 protected QueryParser(CharStream stream) {
488 token_source = new QueryParserTokenManager(stream);
489 token = new Token();
490 jj_ntk = -1;
491 jj_gen = 0;
492 for (int i = 0; i < 23; i++) jj_la1[i] = -1;
493 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
494 }
495
496
497 public void ReInit(CharStream stream) {
498 token_source.ReInit(stream);
499 token = new Token();
500 jj_ntk = -1;
501 jj_gen = 0;
502 for (int i = 0; i < 23; i++) jj_la1[i] = -1;
503 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
504 }
505
506
507 protected QueryParser(QueryParserTokenManager tm) {
508 token_source = tm;
509 token = new Token();
510 jj_ntk = -1;
511 jj_gen = 0;
512 for (int i = 0; i < 23; i++) jj_la1[i] = -1;
513 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
514 }
515
516
517 public void ReInit(QueryParserTokenManager tm) {
518 token_source = tm;
519 token = new Token();
520 jj_ntk = -1;
521 jj_gen = 0;
522 for (int i = 0; i < 23; i++) jj_la1[i] = -1;
523 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
524 }
525
526 private Token jj_consume_token(int kind) throws ParseException {
527 Token oldToken;
528 if ((oldToken = token).next != null) token = token.next;
529 else token = token.next = token_source.getNextToken();
530 jj_ntk = -1;
531 if (token.kind == kind) {
532 jj_gen++;
533 if (++jj_gc > 100) {
534 jj_gc = 0;
535 for (int i = 0; i < jj_2_rtns.length; i++) {
536 JJCalls c = jj_2_rtns[i];
537 while (c != null) {
538 if (c.gen < jj_gen) c.first = null;
539 c = c.next;
540 }
541 }
542 }
543 return token;
544 }
545 token = oldToken;
546 jj_kind = kind;
547 throw generateParseException();
548 }
549
550 static private final class LookaheadSuccess extends java.lang.Error { }
551 final private LookaheadSuccess jj_ls = new LookaheadSuccess();
552 private boolean jj_scan_token(int kind) {
553 if (jj_scanpos == jj_lastpos) {
554 jj_la--;
555 if (jj_scanpos.next == null) {
556 jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
557 } else {
558 jj_lastpos = jj_scanpos = jj_scanpos.next;
559 }
560 } else {
561 jj_scanpos = jj_scanpos.next;
562 }
563 if (jj_rescan) {
564 int i = 0; Token tok = token;
565 while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
566 if (tok != null) jj_add_error_token(kind, i);
567 }
568 if (jj_scanpos.kind != kind) return true;
569 if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
570 return false;
571 }
572
573
574
575 final public Token getNextToken() {
576 if (token.next != null) token = token.next;
577 else token = token.next = token_source.getNextToken();
578 jj_ntk = -1;
579 jj_gen++;
580 return token;
581 }
582
583
584 final public Token getToken(int index) {
585 Token t = token;
586 for (int i = 0; i < index; i++) {
587 if (t.next != null) t = t.next;
588 else t = t.next = token_source.getNextToken();
589 }
590 return t;
591 }
592
593 private int jj_ntk() {
594 if ((jj_nt=token.next) == null)
595 return (jj_ntk = (token.next=token_source.getNextToken()).kind);
596 else
597 return (jj_ntk = jj_nt.kind);
598 }
599
600 private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
601 private int[] jj_expentry;
602 private int jj_kind = -1;
603 private int[] jj_lasttokens = new int[100];
604 private int jj_endpos;
605
606 private void jj_add_error_token(int kind, int pos) {
607 if (pos >= 100) return;
608 if (pos == jj_endpos + 1) {
609 jj_lasttokens[jj_endpos++] = kind;
610 } else if (jj_endpos != 0) {
611 jj_expentry = new int[jj_endpos];
612 for (int i = 0; i < jj_endpos; i++) {
613 jj_expentry[i] = jj_lasttokens[i];
614 }
615 jj_entries_loop: for (java.util.Iterator<?> it = jj_expentries.iterator(); it.hasNext();) {
616 int[] oldentry = (int[])(it.next());
617 if (oldentry.length == jj_expentry.length) {
618 for (int i = 0; i < jj_expentry.length; i++) {
619 if (oldentry[i] != jj_expentry[i]) {
620 continue jj_entries_loop;
621 }
622 }
623 jj_expentries.add(jj_expentry);
624 break jj_entries_loop;
625 }
626 }
627 if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
628 }
629 }
630
631
632 public ParseException generateParseException() {
633 jj_expentries.clear();
634 boolean[] la1tokens = new boolean[40];
635 if (jj_kind >= 0) {
636 la1tokens[jj_kind] = true;
637 jj_kind = -1;
638 }
639 for (int i = 0; i < 23; i++) {
640 if (jj_la1[i] == jj_gen) {
641 for (int j = 0; j < 32; j++) {
642 if ((jj_la1_0[i] & (1<<j)) != 0) {
643 la1tokens[j] = true;
644 }
645 if ((jj_la1_1[i] & (1<<j)) != 0) {
646 la1tokens[32+j] = true;
647 }
648 }
649 }
650 }
651 for (int i = 0; i < 40; i++) {
652 if (la1tokens[i]) {
653 jj_expentry = new int[1];
654 jj_expentry[0] = i;
655 jj_expentries.add(jj_expentry);
656 }
657 }
658 jj_endpos = 0;
659 jj_rescan_token();
660 jj_add_error_token(0, 0);
661 int[][] exptokseq = new int[jj_expentries.size()][];
662 for (int i = 0; i < jj_expentries.size(); i++) {
663 exptokseq[i] = jj_expentries.get(i);
664 }
665 return new ParseException(token, exptokseq, tokenImage);
666 }
667
668
669 final public void enable_tracing() {
670 }
671
672
673 final public void disable_tracing() {
674 }
675
676 private void jj_rescan_token() {
677 jj_rescan = true;
678 for (int i = 0; i < 1; i++) {
679 try {
680 JJCalls p = jj_2_rtns[i];
681 do {
682 if (p.gen > jj_gen) {
683 jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
684 switch (i) {
685 case 0: jj_3_1(); break;
686 }
687 }
688 p = p.next;
689 } while (p != null);
690 } catch(LookaheadSuccess ls) { }
691 }
692 jj_rescan = false;
693 }
694
695 private void jj_save(int index, int xla) {
696 JJCalls p = jj_2_rtns[index];
697 while (p.gen > jj_gen) {
698 if (p.next == null) { p = p.next = new JJCalls(); break; }
699 p = p.next;
700 }
701 p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
702 }
703
704 static final class JJCalls {
705 int gen;
706 Token first;
707 int arg;
708 JJCalls next;
709 }
710
711 }